<!--
* @Description: 表单表格
* @Version: 1.0.1
-->
<template>
  <div class="noe-seve-form-table" ref="noeSeveFormTable">
    <el-table ref="tableRef" v-bind="$attrs" :data="processTableData" :border="border" :row-key="rowKey">
      <slot></slot>
      <el-table-column type="index" width="50" fixed="left" align="center">
        <template #header>
          <el-button v-if="!hideAdd" type="primary" icon="Plus" size="small" circle @click="addRow()"></el-button>
        </template>
        <template #default="scope">
          <div :class="['noe-seve-form-table-handle', 'noe-seve-form-table-handle-delete']">
            <span>{{ scope.$index + 1 }}</span>
            <el-button type="danger" icon="Delete" size="small" plain circle @click="delRow(scope.$index)"></el-button>
          </div>
        </template>
      </el-table-column>

      <template v-for="item in tableColumns" :key="item">
        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="item.type && columnTypes.includes(item.type)">
          <template #default>
            <el-tag v-if="item.type == 'sort'" class="move">
              <el-icon>
                <DCaret />
              </el-icon>
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="!item.type && item.prop">
          <!-- 自定义表格头部内容，slot的格式为 item.prop+Header,例如：#idHeader-->
          <template #header="scope">
            <slot v-if="$slots[item.prop] + 'Header'" :name="item.prop + 'Header'" v-bind="scope" />
          </template>
          <!-- 自定义表格内容，slot的格式为 item.prop,例如：#id-->
          <template #default="scope">
            <slot v-if="$slots[item.prop]" :name="item.prop" v-bind="scope" />
          </template>
        </el-table-column>
      </template>
      <!-- 插入表格最后一行之后的插槽 -->
      <template #append>
        <slot name="append" />
      </template>
      <!-- 无数据 -->
      <template #empty>
        <el-empty :description="emptyText" :image-size="100"></el-empty>
      </template>
    </el-table>
  </div>
</template>

<script setup>
import Sortable from "sortablejs";

const props = defineProps({
  // 列配置项
  columns: {
    type: Array,
    required: true,
  },
  // table data 数据
  data: {
    type: Array,
    required: true,
    default: () => [],
  },
  // 默认数据模板
  dataTemplate: {
    type: Object,
    default: () => {},
  },
  // 是否带有纵向边框
  border: {
    type: Boolean,
    default: true,
  },
  // 行数据的 Key，用来优化 Table 的渲染，所指定的 id
  rowKey: {
    type: String,
    default: "id",
  },
  // 空数据展示提示文字
  emptyText: {
    type: String,
    default: "暂无数据",
  },
  // 是否隐藏新增按钮，默认否
  hideAdd: {
    type: Boolean,
    default: true,
  },
});

const emit = defineEmits();

// table 实例
const tableRef = ref();
// 接收 columns 并设置为响应式
const tableColumns = reactive(props.columns);
// column 列类型
const columnTypes = ["index", "sort"];
const data = ref(props.data);

onMounted(() => {
  dragSort();
});

/**
 * @description 获取表格数据
 */
const processTableData = computed({
  get() {
    return data.value;
  },
  set(newValue) {
    data.value = newValue;
  },
});

/**
 * @description 拖拽排序
 */
const dragSort = () => {
  const tbody = document.querySelector(".el-table__body-wrapper tbody");
  Sortable.create(tbody, {
    handle: ".move",
    animation: 300,
    ghostClass: "ghost",
    onEnd({ newIndex, oldIndex }) {
      const tempList = [...processTableData.value];
      const [removedItem] = tempList.splice(oldIndex, 1);
      tempList.splice(newIndex, 0, removedItem);
      data.value = [];
      nextTick(() => {
        data.value = tempList;
      });
      emit("dargSort", { newIndex, oldIndex });
    },
  });
};

/**
 * @description 新增数据
 * @param row
 */
const addRow = (row) => {
  const data = row ?? JSON.parse(JSON.stringify(props.dataTemplate));
  processTableData.value.push(data);
};

/**
 * @description 删除数据
 * @param index
 */
const delRow = (index) => {
  processTableData.value.splice(index, 1);
};

// 暴露给父组件的参数和方法 (外部需要什么，都可以从这里暴露出去)
defineExpose({
  element: tableRef, // table实例
  tableData: processTableData, // 数据
  addRow,
  delRow,
});
</script>

<style scoped>
.noe-seve-form-table {
  width: 100%;
}

.noe-seve-form-table .noe-seve-form-table-handle {
  text-align: center;
}

.noe-seve-form-table .noe-seve-form-table-handle span {
  display: inline-block;
}

.noe-seve-form-table .noe-seve-form-table-handle button {
  display: none;
}

.noe-seve-form-table .hover-row .noe-seve-form-table-handle-delete span {
  display: none;
}

.noe-seve-form-table .hover-row .noe-seve-form-table-handle-delete button {
  display: inline-block;
}

.noe-seve-form-table .move {
  text-align: center;
  font-size: 14px;
  margin-top: 3px;
}
</style>
